package com.decent.ejfadmin.utils;


import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.HttpClientUtils;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.SocketTimeoutException;
import java.util.HashMap;
import java.util.List;

/**
 * describe:http请求工具类
 *
 * @author 陈豆豆
 * @date 2019/09/07
 */
@SuppressWarnings("StringBufferMayBeStringBuilder")
public final class Httpclient {
    private static final Logger LOGGER = LoggerFactory.getLogger(Httpclient.class);

    /****
     * URL GET连接
     *
     * @param url            get访问URL地址
     * @param connectTimeout 连接超时时间
     * @param socketTimeout  读取超时时间
     * @return http返回值
     */
    public static String get(String url, int connectTimeout, int socketTimeout) {
        String returnStr = "";

        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            HttpGet httpGet = new HttpGet(url);
            RequestConfig config = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
            httpGet.setConfig(config);

            try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    returnStr = EntityUtils.toString(entity);
                }
            }
            httpGet.abort();
        } catch (SocketTimeoutException e) {
            LOGGER.error("地址: {} 读取异常: {}", url, e);
            return "读取超时";
        } catch (ConnectTimeoutException e) {
            LOGGER.error("地址: {} 连接异常: {}", url, e);
            return "";
        } catch (Exception e) {
            LOGGER.error("地址: {} 请求异常: {}", url, e);
            return "请求异常";
        } finally {
            HttpClientUtils.closeQuietly(httpClient);
        }
        return returnStr;
    }

    /****
     * URL POST访问
     *
     * @param url            地址
     * @param params         POST内容
     * @param charset        编码格式
     * @param connectTimeout 连接超时时间
     * @param socketTimeout  读取超时时间
     * @return http返回值
     */
    public static String post(String url, List<NameValuePair> params, String charset, int connectTimeout, int socketTimeout) {
        String returnStr;

        CloseableHttpClient httpClient = null;
        CloseableHttpResponse httpResponse = null;
        try {
            UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, charset);
            httpClient = HttpClients.createDefault();

            HttpPost httpPost = new HttpPost(url);
            entity.setContentEncoding(charset);
            httpPost.setEntity(entity);

            RequestConfig config = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
            httpPost.setConfig(config);

            httpResponse = httpClient.execute(httpPost);

            BufferedReader reader = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent(), charset));
            StringBuffer stringBuffer = new StringBuffer(100);
            String str;
            while ((str = reader.readLine()) != null) {
                stringBuffer.append(str);
            }
            returnStr = stringBuffer.toString();
            reader.close();
        } catch (SocketTimeoutException e) {
            LOGGER.error("地址: {}|参数: {} 读取异常: {}", url, params, e);
            return "读取超时";
        } catch (ConnectTimeoutException e) {
            LOGGER.error("地址: {}|参数: {} 连接异常: {}", url, params, e);
            return "";
        } catch (Exception e) {
            LOGGER.error("地址: {}|参数: {} 请求异常: {}", url, params, e);
            return "请求异常";
        } finally {

            HttpClientUtils.closeQuietly(httpResponse);
            HttpClientUtils.closeQuietly(httpClient);
        }
        return returnStr;
    }

    /****
     * URL POST获取文件流
     *
     * @param url            地址
     * @param params         POST内容
     * @param charset        编码格式
     * @param connectTimeout 连接超时时间
     * @param socketTimeout  读取超时时间
     */
    public static void postStream(String url, List<NameValuePair> params, String charset, int connectTimeout, int socketTimeout, HttpServletResponse response) {
        response.setContentType("application/msdownload");
        response.setHeader("Content-Disposition", "attachment;filename=" + System.currentTimeMillis() + ".zip");
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse httpResponse = null;
        try {
            UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, charset);

            httpClient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(url);
            entity.setContentEncoding(charset);
            httpPost.setEntity(entity);
            RequestConfig config = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
            httpPost.setConfig(config);

            httpResponse = httpClient.execute(httpPost);

            HttpEntity resultEntity = httpResponse.getEntity();
            ServletOutputStream outputStream = response.getOutputStream();
            resultEntity.writeTo(outputStream);
            outputStream.flush();
            outputStream.close();
//            BufferedReader reader = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent(), charset));
//            StringBuffer stringBuffer = new StringBuffer(100);
//            String str;
//            while ((str = reader.readLine()) != null) {
//                stringBuffer.append(str);
//            }
//            System.out.println(stringBuffer.toString());

        } catch (Exception e) {
            LOGGER.error("地址: {} 请求异常: {}", url, e);
        } finally {
            HttpClientUtils.closeQuietly(httpResponse);
            HttpClientUtils.closeQuietly(httpClient);
        }
    }

    /**
     * POST 发送json请求
     *
     * @param url            地址
     * @param params         参数集合
     * @param socketTimeout  读取超时时间（毫秒）
     * @param connectTimeout 链接超时时间（毫秒）
     * @return 响应
     */
    public static String postJson(String url, HashMap<String, Object> params, int socketTimeout, int connectTimeout) {
        CloseableHttpClient client = null;
        HttpResponse httpResponse = null;
        String result;
        try {
            client = HttpClients.createDefault();
            HttpPost method = new HttpPost(url);

            ObjectMapper mapper = new ObjectMapper();

            StringEntity entity = new StringEntity(mapper.writeValueAsString(params), "UTF-8");
            entity.setContentEncoding("UTF-8");
            entity.setContentType("application/json");
            method.setEntity(entity);

            RequestConfig config = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
            method.setConfig(config);

            httpResponse = client.execute(method);

            result = EntityUtils.toString(httpResponse.getEntity());
        } catch (SocketTimeoutException e) {
            LOGGER.error("地址: {}|参数: {} 读取异常: {}", url, params, e);
            return "读取超时";
        } catch (ConnectTimeoutException e) {
            LOGGER.error("地址: {}|参数: {} 连接异常: {}", url, params, e);
            return "";
        } catch (Exception e) {
            LOGGER.error("地址: {}|参数: {} 请求异常: {}", url, params, e);
            return "请求异常";
        } finally {
            HttpClientUtils.closeQuietly(httpResponse);
            HttpClientUtils.closeQuietly(client);
        }
        return result;
    }
}
